package com.bkgy.modular.calsidata.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baosight.hdsdk.domain.data.HDDataConnection;
import com.baosight.hdsdk.domain.data.HDRecord;
import com.baosight.hdsdk.exception.HDSdkException;
import com.bkgy.modular.calsidata.dao.SiDataBX1Dao;
import com.bkgy.modular.calsidata.dao.TPdoListDao;
import com.bkgy.modular.calsidata.dao.TbDsjC621EdgePassTimeDao;
import com.bkgy.modular.calsidata.dao.TbEdgeDao;
import com.bkgy.modular.calsidata.entity.TPdoList;
import com.bkgy.modular.calsidata.entity.TbDsjC621EdgePassTime;
import com.bkgy.modular.calsidata.entity.TbEdge;
import com.bkgy.controller.tbbxrecord.entity.TbBxFileSave;
import com.bkgy.modular.tbdsjdatacollect.dao.TbDsjDataCollectDao;
import com.bkgy.modular.tbdsjdatacollect.entity.TbDsjDataCollect;
import com.bkgy.util.PdoUtils;
import com.bkgy.util.SDKUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 硅钢数据处理第一步
 */
@Service
@Slf4j
public class SiDataBX1Service {

    @Resource
    private SiDataBX1Dao siDataBX1Dao;
    @Resource
    private TbEdgeDao tbEdgeDao;
    @Resource
    private TbDsjC621EdgePassTimeDao tbDsjC621EdgePassTimeDao;
    @Resource
    private TbDsjDataCollectDao tbDsjDataCollectDao;
    @Resource
    private SDKUtils sdkUtils;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private TPdoListDao tPdoListDao;

    @Autowired
    private PdoUtils pdoUtils;

    /**
     * 查找数组中指定范围内的最大值
     *
     * @param list 数组
     * @param L    从位置L
     * @param R    至位置R
     * @return 值
     */
    private static Double recursion(List<Double> list, int L, int R) {
        if (L == R || L > R) {
            return list.get(L);
        }
        List<Double> listx = new ArrayList<>();
        for (int i = L; i < R; i++) {
            listx.add(list.get(i));
        }
        return listx.stream().mapToDouble(x -> x).max().orElse(0.0D);
    }

    //@Scheduled(cron = "${cronTime2}")//定时在112全打开，113，115全部关闭
    public void readSiData1() {
        log.error("SiDataBX1Service+readSiData1：");
        log.error("进查询");
        try {
            QueryWrapper<TbDsjC621EdgePassTime> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda().orderByDesc(TbDsjC621EdgePassTime::getId).last(" FETCH FIRST 1 ROWS ONLY");
            TbDsjC621EdgePassTime tbDsjC621EdgePassTime = tbDsjC621EdgePassTimeDao.selectOne(wrapper1);

            /*QueryWrapper<SiDataBX1> wrapper2 = new QueryWrapper<>();
            wrapper2.lambda().gt(StringUtils.hasText(tbDsjC621EdgePassTime.getProcess_end_time().toString()), SiDataBX1::getProcess_end_time, tbDsjC621EdgePassTime.getProcess_end_time())
                    .isNotNull(SiDataBX1::getProcess_end_time);*/
//            wrapper2.lambda().gt(SiDataBX1::getProcess_end_time,"2023-07-09 05:43:57");
            LambdaQueryWrapper<TPdoList> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.gt(StringUtils.hasText(tbDsjC621EdgePassTime.getProcess_end_time().toString()),
                    TPdoList::getEndtime, tbDsjC621EdgePassTime.getProcess_end_time()).isNotNull(TPdoList::getEndtime);


//            wrapper2.gt(StringUtils.hasText(tbDsjC621EdgePassTime.getProcess_end_time().toString()),
//                    TPdoList::getEndtime, "2023-07-07 15:40:30").isNotNull(TPdoList::getEndtime).orderByAsc(TPdoList::getEndtime);

            // 查询出宝信的pdo数据
            List<TPdoList> list = tPdoListDao.selectList(wrapper2);
//            list = list.subList(0,1);

            for (TPdoList siDataBX1 : list) {
                TbBxFileSave tbBxFileSave = new TbBxFileSave();
                tbBxFileSave.setMessage("最复杂");
                pdoUtils.calPdo621(siDataBX1.getExtid(), tbBxFileSave);
            }

            HDDataConnection connect = sdkUtils.getConnect();
            while (!connect.isConnected()) {
                connect = sdkUtils.getConnect();
            }
            Integer id = sdkUtils.findTagId("C621_N121D5_1", connect.getTagManager());
            TPdoList tPdoList = null;
            // 循环读取获取到的还未处理的最新卷号时间
            for (TPdoList item : list) {
                HDRecord hdRecord = null;
                LocalDateTime pdoDataDate = item.getEndtime().toLocalDateTime();
                //pdolist结束时间增加一秒去实时数据库查
                pdoDataDate = pdoDataDate.plusSeconds(1L);

                // 修改
                LocalDateTime startTime = item.getStarttime().toLocalDateTime();
                if (Duration.between(startTime, pdoDataDate).toMinutes() < 30) {
                    //限制最多查询30分钟
                    LocalDateTime stuTime = pdoDataDate.minusMinutes(20); // time1减去30分钟并返回
                    LocalDateTime pdoDataDate2 = pdoDataDate.minusMinutes(5); // time1减去5分钟并返回
                    int a = 1;
                    while (a == 1) {
                        List<HDRecord> hdRecords = sdkUtils.findMsgByIdAndTime(id, connect.getDataProvider(), pdoDataDate2, pdoDataDate);
                        for (int i = 0; i < hdRecords.size(); i++) {
                            if (hdRecords.get(i).getValueStr().equals("1.0")) {
                                if (i == 0) {
                                    hdRecord = hdRecords.get(i);
                                } else {
                                    hdRecord = hdRecords.get(i - 1);
                                }
                                a = 0;
                                break;
                            }
                        }
                        pdoDataDate = pdoDataDate.minusMinutes(5);
                        pdoDataDate2 = pdoDataDate2.minusMinutes(5);
                        // time2是否等于stuTime
                        if (pdoDataDate2.isEqual(stuTime) || a == 0) {
                            a = 0;
                            break;
                        }
                    }

                    //上条数据
                    TbDsjC621EdgePassTime latestData = null;
                    // if (!ObjectUtils.isEmpty(hdRecord)) {
                    //存数据库
                    QueryWrapper<TbDsjC621EdgePassTime> wrapper = new QueryWrapper<>();
                    wrapper.lambda().orderByDesc(TbDsjC621EdgePassTime::getId).lt(TbDsjC621EdgePassTime::getProcess_end_time, item.getEndtime()).last(" FETCH FIRST 1 ROWS ONLY");
                    // wrapper.lambda().orderByDesc(TbDsjC621EdgePassTime::getId).eq(TbDsjC621EdgePassTime::getCoil_id,"M3050486000");
                    //查询上条数据
                    latestData = tbDsjC621EdgePassTimeDao.selectOne(wrapper);
                    // }

                    LocalDateTime localDateTime = null;
                    if (!ObjectUtils.isEmpty(hdRecord)) {
                        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS");
                        localDateTime = LocalDateTime.parse(hdRecord.getTimeStampStr(), pattern);
                    }
                    LambdaQueryWrapper<TPdoList> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(TPdoList::getExtid, item.getExtid());
                    tPdoList = tPdoListDao.selectOne(queryWrapper);
                    if (tPdoList != null) {
                        if (localDateTime != null) {
                            if (!ObjectUtils.isEmpty(latestData) && latestData.getPass_device_end_time() != null && Timestamp.valueOf(localDateTime) != null) {
                                // 上条数据的结束时间大于等于本条结束时间的时候
                                if (latestData.getPass_device_end_time().getTime() >= Timestamp.valueOf(localDateTime).getTime()) {
                                    TbDsjC621EdgePassTime tbDsjC621EdgePassTime1 = new TbDsjC621EdgePassTime();
                                    tbDsjC621EdgePassTime1.setCoil_id(item.getExtid());
                                    tbDsjC621EdgePassTime1.setHot_coil_id(item.getEntid());
                                    log.error("1上个卷号" + latestData.getCoil_id() + "时间:" + latestData.getPass_device_end_time() + "和当前卷号" + item.getExtid() + "时间:" + localDateTime);
                                    tbDsjC621EdgePassTime1.setPass_device_end_time(tPdoList.getEndtime()); // T_PDO_DATA
                                    tbDsjC621EdgePassTime1.setProcess_end_time(tPdoList.getEndtime()); // T_PDO_DATA
                                    tbDsjC621EdgePassTime1.setPass_device_start_time(latestData.getPass_device_end_time()); // 上条数据
                                    tbDsjC621EdgePassTime1.setFlag(1);
                                    //插入最新数据
                                    QueryWrapper<TbDsjC621EdgePassTime> wrapper3 = new QueryWrapper<>();
                                    wrapper3.eq("coil_id", tbDsjC621EdgePassTime1.getCoil_id());
                                    Long count = tbDsjC621EdgePassTimeDao.selectCount(wrapper3);
                                    if (count <= 0) {
                                        tbDsjC621EdgePassTimeDao.insert(tbDsjC621EdgePassTime1);
                                    }
                                } else {
                                    TbDsjC621EdgePassTime data = new TbDsjC621EdgePassTime();
                                    data.setCoil_id(item.getExtid())
                                            .setHot_coil_id(item.getEntid())
                                            .setProcess_end_time(tPdoList.getEndtime());

                                    if (!ObjectUtils.isEmpty(latestData)) {
                                        data.setPass_device_start_time(latestData.getPass_device_end_time());
                                    }

                                    if (!ObjectUtils.isEmpty(hdRecord)) {
                                        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS");
                                        LocalDateTime parse1 = LocalDateTime.parse(hdRecord.getTimeStampStr(), pattern);

                                        // TODO 六月6日修改 PASS_DEVICE_START_TIME&PASS_DEVICE_END_TIME间隔时间短的问题
                                        if (Duration.between(data.getPass_device_start_time().toLocalDateTime(), parse1).toMinutes() > 1) {
                                            // 判断卷号结尾是否为0,不为0的话Pass_device_end_time值使用process_end_time
                                            Timestamp value1 = Timestamp.valueOf(parse1);
                                            Timestamp value2 = tPdoList.getEndtime();
                                            if (value2.toLocalDateTime().isAfter(value1.toLocalDateTime().plusSeconds(2L))) {
                                                data.setPass_device_end_time(value2);
                                            } else {
                                                data.setPass_device_end_time(value1);
                                            }

//                                            data.setPass_device_end_time(
//                                                    item.getExtid().endsWith("0") ?
//                                                            Timestamp.valueOf(parse1) :
//                                                            tPdoList.getEndtime());
                                        } else {
                                            log.error("2上个卷号" + latestData.getCoil_id() + "和当前卷号" + item.getExtid());
                                            data.setPass_device_end_time(item.getEndtime());
                                        }

                                        /* if ((data.getPass_device_start_time().toLocalDateTime()).equals(parse1)) {
                                            log.error("2上个卷号" + latestData.getCoil_id()+ "和当前卷号" +siDataBX1.getExtid());
                                            data.setPass_device_end_time(siDataBX1.getProcess_end_time());
                                        } else {
                                            data.setPass_device_end_time(Timestamp.valueOf(parse1));
                                        }*/
                                        data.setFlag(1);
                                    }
                                    //插入最新数据
                                    QueryWrapper<TbDsjC621EdgePassTime> wrapper3 = new QueryWrapper<>();
                                    wrapper3.eq("coil_id", data.getCoil_id());
                                    Long count = tbDsjC621EdgePassTimeDao.selectCount(wrapper3);
                                    if (count <= 0) {
                                        tbDsjC621EdgePassTimeDao.insert(data);
                                    }
                                }
                            } else {
                                TbDsjC621EdgePassTime data = new TbDsjC621EdgePassTime();
                                log.error("3上个卷号" + latestData.getCoil_id() + "和当前卷号" + item.getExtid());
                                data.setCoil_id(item.getExtid())
                                        .setHot_coil_id(item.getEntid())
                                        .setProcess_end_time(tPdoList.getEndtime())
                                        .setPass_device_start_time(latestData.getPass_device_end_time())
                                        .setPass_device_end_time(tPdoList.getEndtime())
                                        .setFlag(1);
                                //插入最新数据
                                QueryWrapper<TbDsjC621EdgePassTime> wrapper3 = new QueryWrapper<>();
                                wrapper3.eq("coil_id", data.getCoil_id());
                                Long count = tbDsjC621EdgePassTimeDao.selectCount(wrapper3);
                                if (count <= 0) {
                                    tbDsjC621EdgePassTimeDao.insert(data);
                                }
                            }
                        } else {
                            TbDsjC621EdgePassTime data = new TbDsjC621EdgePassTime();

                            log.error("4上个卷号" + latestData.getCoil_id() + "和当前卷号" + item.getExtid());
                            data.setCoil_id(item.getExtid())
                                    .setHot_coil_id(item.getEntid())
                                    .setProcess_end_time(tPdoList.getEndtime())
                                    .setPass_device_start_time(latestData.getPass_device_end_time())
                                    .setPass_device_end_time(tPdoList.getEndtime())
                                    .setFlag(1);
                            //插入最新数据
                            QueryWrapper<TbDsjC621EdgePassTime> wrapper3 = new QueryWrapper<>();
                            wrapper3.eq("coil_id", data.getCoil_id());
                            Long count = tbDsjC621EdgePassTimeDao.selectCount(wrapper3);
                            if (count <= 0) {
                                tbDsjC621EdgePassTimeDao.insert(data);
                            }
                        }
                    }
                } else {
                    //上条数据
                    TbDsjC621EdgePassTime latestData = null;
                    //存数据库
                    QueryWrapper<TbDsjC621EdgePassTime> wrapper = new QueryWrapper<>();
                    wrapper.lambda().orderByDesc(TbDsjC621EdgePassTime::getId).last(" FETCH FIRST 1 ROWS ONLY");
                    //查询上条数据
                    latestData = tbDsjC621EdgePassTimeDao.selectOne(wrapper);

                    LambdaQueryWrapper<TPdoList> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(TPdoList::getExtid, item.getExtid());
                    tPdoList = tPdoListDao.selectOne(queryWrapper);
                    if (tPdoList != null) {
                        TbDsjC621EdgePassTime tbDsjC621EdgePassTime1 = new TbDsjC621EdgePassTime();
                        tbDsjC621EdgePassTime1.setCoil_id(item.getExtid());
                        tbDsjC621EdgePassTime1.setHot_coil_id(item.getEntid());
                        tbDsjC621EdgePassTime1.setProcess_end_time(tPdoList.getEndtime());
                        log.error("5上个卷号" + latestData.getCoil_id() + "和当前卷号" + item.getExtid());
                        tbDsjC621EdgePassTime1.setPass_device_end_time(tPdoList.getEndtime());
                        if (latestData == null) {
                            tbDsjC621EdgePassTime1.setPass_device_start_time(null);
                        } else {
                            tbDsjC621EdgePassTime1.setPass_device_start_time(latestData.getPass_device_end_time());
                        }
                        tbDsjC621EdgePassTime1.setFlag(1);
                        //插入最新数据
                        QueryWrapper<TbDsjC621EdgePassTime> wrapper3 = new QueryWrapper<>();
                        wrapper3.eq("coil_id", tbDsjC621EdgePassTime1.getCoil_id());
                        Long count = tbDsjC621EdgePassTimeDao.selectCount(wrapper3);
                        if (count <= 0) {
                            tbDsjC621EdgePassTimeDao.insert(tbDsjC621EdgePassTime1);
                        }
                    }
                }
            }
            try {
                connect.dispose();
            } catch (HDSdkException e) {
                log.error("TbRealTimeVariableServiceImpl+getRealValue释放失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //@Scheduled(cron = "${cronTime3}")//定时在112全打开，113，115全部关闭
    public void saveSiData() throws HDSdkException {
        try {
            log.error("SiDataBX1Service+saveSiData：进保存");
            //查找需要查询的sdk变量名，别名
            QueryWrapper<TbDsjDataCollect> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda().eq(TbDsjDataCollect::getOut_data_source, "6.0");
            List<TbDsjDataCollect> list1 = tbDsjDataCollectDao.selectList(wrapper1);

            //查找还未处理的卷
            QueryWrapper<TbDsjC621EdgePassTime> wrapper2 = new QueryWrapper<>();
            wrapper2.lambda().eq(TbDsjC621EdgePassTime::getFlag, 1).orderByAsc(TbDsjC621EdgePassTime::getProcess_end_time);
            List<TbDsjC621EdgePassTime> list2 = tbDsjC621EdgePassTimeDao.selectList(wrapper2);
            List<TbDsjC621EdgePassTime> list3 = new ArrayList<>();
            if (!CollectionUtils.isEmpty(list2)) {
                list3.add(list2.get(0));
            }
            TbEdge tbEdge = new TbEdge();
            Map<String, Object> edge = new HashMap<>();
            long len = 0L;
            HDDataConnection connect = sdkUtils.getConnect();
            //循环获取时间范围
            while(!connect.isConnected()) {
                log.error("SiDataBX1Service+saveSiData+connect未连上，重新连接");
                connect = sdkUtils.getConnect();
            }
            for (TbDsjC621EdgePassTime data : list3) {
                if (!String.valueOf(data.getPass_device_start_time()).equals("null") && !String.valueOf(data.getPass_device_end_time()).equals("null") && StringUtils.hasText(String.valueOf(data.getPass_device_start_time())) && StringUtils.hasText(String.valueOf(data.getPass_device_end_time()))) {
                    LocalDateTime start_time = data.getPass_device_start_time().toLocalDateTime();
                    LocalDateTime end_time = data.getPass_device_end_time().toLocalDateTime();

                    if (start_time.plusMinutes(20L).isBefore(end_time)) {
                        data.setFlag(3);
                        tbDsjC621EdgePassTimeDao.updateById(data);
                        tbEdge.setExtid(data.getCoil_id());
                        sendmessage(tbEdge);
                    } else {
                        if (start_time.isBefore(end_time)) {
                            //带入卷号
                            tbEdge.setExtid(data.getCoil_id());
                            // List<Double> length = new ArrayList<>();
                            List<Double> thick_lmi = new ArrayList<>();

                            List<HDRecord> list_length = sdkUtils.findMsgByIdAndTime(
                                    sdkUtils.findTagId("C621_N11B01", connect.getTagManager()), connect.getDataProvider(), start_time, end_time);
                            Collections.reverse(list_length);

                            // 积分值
                            Double integral = 0.0;
                            List<Double> length = new ArrayList<>();
                            for (HDRecord hdRecord : list_length) {
                                String timeStampStr = hdRecord.getTimeStampStr();
                                String valueStr = hdRecord.getValueStr();
                                integral += Double.parseDouble(valueStr) * 20 / 60 / 1000;
                                length.add(integral);
                            }

                            //获取长度
                    /*length = list_length.stream().filter(x -> StringUtils.hasText(x.getValueStr()))
                            .map(x -> Double.parseDouble(x.getValueStr())).sorted().collect(Collectors.toList());*/

                            // long length = Math.round(integral);
                            List<String> stringList = new ArrayList<>();
                            for (TbDsjDataCollect item : list1) {
                                stringList.add(item.getL1_variable_name());
                            }
                            List<ImmutablePair<Integer, Integer>> tagIDsByTagNamesList = sdkUtils.findTagIDsByTagNames(stringList, connect.getTagManager());
                            int i2 = 0;
                            //根据变量名循环获取tagid
                            for (TbDsjDataCollect entity : list1) {
                                // 处理除此之外的其他变量
                                //if (!entity.getL1_variable_name().contains("C621_VM_MDV_01_4VFB")) {
                                List<HDRecord> list_length2 = sdkUtils.findMsgByIdAndTime(tagIDsByTagNamesList.get(i2).getLeft(), connect.getDataProvider(), start_time, end_time);
                                Collections.reverse(list_length2);
                                //获取要计算的值的集合 null
                                List<Double> thick = list_length2.stream().filter(x -> StringUtils.hasText(x.getValueStr()))
                                        .map(x -> Double.parseDouble(x.getValueStr())).collect(Collectors.toList());
                                //根据变量名、时间范围，计算转换出需要的值集合
                                thick_lmi = changeData(length, thick);
                                //获取别名,并存储转换后的对应数据
                                edge.put(entity.getL1_variable_alias(), thick_lmi);
                                len = thick_lmi.size();
                                i2++;
                                //}
                            }
                        }
                        //改变标识符
                        data.setFlag(2);
                        tbDsjC621EdgePassTimeDao.updateById(data);
                        tbEdge.setEdge(edge);
                        tbEdge.setLength(len);
                        tbEdge.setCreatetime(new Date());
                        tbEdgeDao.save(tbEdge);
                        sendmessage(tbEdge);
                    }


                } else {
                    //改变标识符
                    data.setFlag(2);
                    tbDsjC621EdgePassTimeDao.updateById(data);
                }

            }

            try {
                connect.dispose();
            } catch (HDSdkException e) {
                log.error("SiDataBX1Service+saveSiData+connect释放失败");
            }

        } catch (Exception e) {
            log.error(e.toString());
            e.printStackTrace();
        }
    }

    private void sendmessage(TbEdge tbEdge) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("volumeNo", tbEdge.getExtid());
        jsonObject.put("line", "C1720");
        String jsonString = jsonObject.toJSONString();
        restTemplate.postForObject("http://170.0.200.112:1234/send_msg_to_models", jsonString, String.class);
    }

    private List<Double> changeData(List<Double> length, List<Double> thick) {
        List<Double> thick_lmi = new ArrayList<>();
        int M = thick.size();
        double N = length.stream().mapToDouble(x -> x).max().orElse(0.0D);//最大值
//        double N = length.get(0);//最大值
//        log.info("N是:  -----"+N);
//        log.info("M是:  -----"+M);
//        log.info("length.size是:  -----"+length.size());
        //补充thick长度和lenth至一致
        if (M < length.size()) {
            for (int j = thick.size(); j < length.size(); j++) {
                if (j > 0) {
                    thick.add(j, thick.get(j - 1));
                }
            }
        }
        int index = 0;
        for (int n = 0; n < N; n++) {
            for (int m = index; m < M; m++) {
                if (m < length.size() && length.get(m) > n + 1 && index <= m - 1) {
//                    log.info("n是:  -----"+n);
//                    log.info("length.get(m)是:  -----"+length.get(m));
                    thick_lmi.add(n, recursion(thick, index, m - 1));
                    index = m;
                    break;
                }
            }
        }
        return thick_lmi;
    }
}
